package com.xlh.virtualization.job.delayed;

import com.xlh.util.SpringContextUtil;
import com.xlh.virtualization.dao.helper.ContainerMapperHelper;
import com.xlh.virtualization.domain.Container;
import com.xlh.virtualization.properties.ContainerProperties;
import com.xlh.virtualization.service.ContainerService;
import com.xlh.virtualization.service.ExperimentService;
import com.xlh.virtualization.websocket.CourseExperimentWebsocket;
import com.xlh.virtualization.websocket.RedirectToTheoryWebsocket;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.DelayQueue;

import static com.xlh.virtualization.constant.ContainerStatusEnum.STOPPING;
import static com.xlh.virtualization.constant.ContextTypeEnum.COURSE;
import static com.xlh.virtualization.constant.ContextTypeEnum.TASK;

/**
 * 延迟任务监听器
 *
 * @author cheer
 */
@Component
@Slf4j
public class StopContainerListener implements ApplicationListener<ApplicationReadyEvent> {

    private static DelayQueue<StopContainerTask> delayQueue = new DelayQueue<>();

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Autowired
    private ContainerProperties containerProperties;

    @Autowired
    private ContainerService containerService;

    @Autowired
    private ExperimentService experimentService;

    @Autowired
    private ContainerMapperHelper containerMapperHelper;

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        // 服务器启动后根据配置决定是否停止处于运行状态的容器
        if (containerProperties.getStopContainersWhenInit()) {
            List<Container> containers = containerMapperHelper.listRunningContainers();
            for (Container container : containers) {
                if (!experimentService.isExperimentPageOpen(container.getUserId(), container.getContextType(),
                        container.getContextId())) {
                    containerService.stopContainer(container);
                }
            }
        }

        // 启动一个线程进行任务分配
        new Thread(() -> {
            while (true) {
                try {
                    StopContainerTask stopContainerTask = delayQueue.take();
                    threadPoolTaskExecutor.execute(stopContainerTask);
                } catch (Exception e) {
                    log.error("延迟停止容器异常", e);
                }
            }
        }).start();
    }

    public static void putTask(StopContainerTask task) {
        ThreadPoolTaskScheduler taskScheduler = SpringContextUtil.getBean(ThreadPoolTaskScheduler.class);
        ContainerMapperHelper containerMapperHelper = SpringContextUtil.getBean(ContainerMapperHelper.class);
        if (Objects.equals(task.getContextType(), COURSE.getCode()) || Objects.equals(task.getContextType(), TASK.getCode())) {
            taskScheduler.schedule(() -> {
                if (!CourseExperimentWebsocket.isOnline(task.getContainerContext()) &&
                        !RedirectToTheoryWebsocket.isOnline(task.getContainerContext())) {
                    containerMapperHelper.updateStatus(task.getUserId(), task.getContextType(), task.getContextId(),
                            STOPPING.getCode());
                }
            }, new Date(System.currentTimeMillis() + 5000));
        } else {
            containerMapperHelper.updateStatus(task.getUserId(), task.getContextType(), task.getContextId(),
                    STOPPING.getCode());
        }
        delayQueue.put(task);
    }
}
